POSTIT = {
  Autotag: '<div postit="Title">Message.</div>',
  MaxZ: 0,
  Id_Prefix: 'mOvEaBlE',
  Old_X: 0,
  Old_Y: 0,
  Obj: null,
  Left: 0,
  Top: 0,
  Dragged: false,
  Mesg: null,

  raise: function (obj) {
	if (obj.style.zIndex < POSTIT.MaxZ ) {
		POSTIT.MaxZ++;
		obj.style.zIndex = POSTIT.MaxZ;
	}
  },

  hide: function (id) {
	var el = document.getElementById(id);
	el.innerHTML = "";
	el.style.visibility="hidden";
  },

  pos_x: function (e) {
	var posx = 0;
	if (!e) e = window.event;
	if (e.pageX) {
		posx = e.pageX;
	} else if (e.clientX) {
		posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
	}
	return posx;
  },

  pos_y: function (e) {
	var posy = 0;
	if (!e) e = window.event;
	if (e.pageY) {
		posy = e.pageY;
	} else if (e.clientY) {
		posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
	}
	return posy;
  },

  save_pos: function (e) {
	POSTIT.last_x = POSTIT.pos_x(e);
	POSTIT.last_y = POSTIT.pos_y(e);
  },

  select: function (e) {
	var moz = document.getElementById && !document.all;
	var top_elem = moz ? "HTML" : "BODY";
	var obj = e == undefined ? event.srcElement : e.target;
	while (obj.tagName != top_elem && obj.style.cursor != 'move') {
		obj = moz ? obj.parentNode : obj.parentElement;
	}
	if (obj.style.cursor != 'move') return;
	while (obj.tagName != top_elem && obj.style.position != 'absolute') {
		obj = moz ? obj.parentNode : obj.parentElement;
	}
	if (obj.style.position != 'absolute') return;
	POSTIT.raise(obj);
	POSTIT.Dragged = true;
	POSTIT.Obj = obj;
	POSTIT.Left = parseInt(obj.style.left + 0);
	POSTIT.Top  = parseInt(obj.style.top + 0);
	POSTIT.Old_X = POSTIT.pos_x(e);
	POSTIT.Old_Y = POSTIT.pos_y(e);
	document.onmousemove = POSTIT.move;
	return false;
  },

  move: function (e) {
	if (POSTIT.Dragged) {
		var x = POSTIT.pos_x(e);
		var y = POSTIT.pos_y(e);
		POSTIT.Obj.style.left = POSTIT.Left - POSTIT.Old_X + x;
		POSTIT.Obj.style.top  = POSTIT.Top  - POSTIT.Old_Y + y;
		if (POSTIT.mesg) {
			POSTIT.mesg.innerHTML = 'Id='+POSTIT.Obj.id+' Left='+POSTIT.Left+' Top='+POSTIT.Top+' dX='+x+' - '+POSTIT.Old_X+' dY='+y+' - '+POSTIT.Old_Y;
		}
		return false;
	}
  },

  create: function (obj) {
	var head = obj.getAttribute('postit');
	if (head == undefined || head.length == 0) { return; }
	var window_w = BROWSER.size('w');
	var min_left = (window_w - 800)/2;
	var opacity= DYN.get_attr(obj, 'opacity', /(\d+)/, 80);
	var width  = DYN.get_attr(obj, 'width',  /(\d+)/, 320);
	var height = DYN.get_attr(obj, 'height', /(\d+)/, 240);
	var left   = DYN.get_attr(obj, 'left', /([cr]?[+-]?\d+)/, RANDOM.integer(min_left, 800+min_left-width));
	var top_   = DYN.get_attr(obj, 'top',  /([mb]?[+-]?\d+)/, RANDOM.integer(300, BROWSER.size('h') - height - 20));
	var bg     = DYN.get_attr(obj, 'bg', /(#[\da-f]{6}|[a-z]+)/, RANDOM.color(160,160,160,255,255,255));
	if (/^c-(\d+)/.test(left)) {
		left = Math.floor(window_w/2 - RegExp.$1);
	} else if (/^c+?(\d+)/.test(left)) {
		left = Math.floor(window_w/2 + RegExp.$1);
	} else if (/^r-?(\d+)/.test(left)) {
		left = window_w - RegExp.$1;
	}
	if (/^m-(\d+)/.test(top_)) {
		top_ = Math.floor(height/2 - RegExp.$1);
	} else if (/^m+?(\d+)/.test(top_)) {
		top_ = Math.floor(height/2 + RegExp.$1);
	} else if (/^b-?(\d+)/.test(top_)) {
		top_ = BROWSER.size('h') - RegExp.$1;
	}
	opacity = document.getElementById && !document.all ? STR.prf('-moz-opacity:%s', opacity/100) : STR.prf('filter: alpha(opacity=%s)', opacity);
	var html = obj.innerHTML;
	var zindex = ++POSTIT.MaxZ;
	var id = POSTIT.Id_Prefix + "" + POSTIT.MaxZ;
	var new_div = STR.prf('<div id="%s" style="position:absolute; z-index:%s; left:%s; top:%s; background-color:%s; %s"><table width="%s" style="border:1px solid #cc9966"><tr height="20"><td style="cursor:move">%s</td><td width="15" style="cursor:pointer" valign="middle"><img onclick="POSTIT.hide(\'%s\')" width=9 src="/im/x.png" /></td></tr><tr height="%s"><td colspan="2">%s</td></tr></table></div>', id, zindex,left, top_, bg, opacity, width, head, id, height, html);
	return new_div;
  },

  render: function (obj_array) {
	for (var i = 0; i<obj_array.length; i++) {
		var obj = obj_array[i];
		if (obj.style.position == 'absolute') continue;
		var new_div = POSTIT.create(obj);
		if (new_div) { obj.innerHTML = new_div;}
	}
	document.onmousedown=POSTIT.select;
	document.onmouseup=new Function("POSTIT.Dragged=false");
  }
};

TYPIST = {
  Autotag: '<div type=typist interval=30000 speed=300>Hi, I am a typist.</div>',
  text: "",
  pos: 1,
  obj: "",
  pause: false,
  interval: 30000,
  speed: 300,
  nl: new RegExp('\n', 'g'),
  setup: function(obj) {
	TYPIST.obj = obj;
	TYPIST.text = obj.innerHTML;
	obj.setAttribute('onclick', 'TYPIST.toggle_pause()');
	TYPIST.interval = DYN.get_attr(obj, 'interval', /(\d+)/, 30000);
	TYPIST.speed = DYN.get_attr(obj, 'speed', /(\d+)/, 300);
	TYPIST.type_slowly();
  },
  type_slowly: function() {
	if (TYPIST.pause) return;
	if (TYPIST.obj) {
		TYPIST.obj.innerHTML = TYPIST.text.substr(0, TYPIST.pos).replace(TYPIST.nl, '<br/>') + '_';
		TYPIST.pos++;
		if (TYPIST.pos > TYPIST.text.length) {
			TYPIST.pos = 1;
			setTimeout("TYPIST.type_slowly()", TYPIST.interval);
		} else {
			setTimeout("TYPIST.type_slowly()", RANDOM.integer(10, TYPIST.speed));
		}
	}
  },
  toggle_pause: function() {
	if(TYPIST.pause) {
		TYPIST.pause = false;
		TYPIST.type_slowly();
		return false;
	}
	TYPIST.pause=true;
	return false;
  }
};

CHESS = {
  Autotag: '<div type=chessboard white="Ke3Qd4" black="Ka5Qb6"></div>',
  Files: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
  get: function (obj, attr, re, deflt) {
	var v = obj.getAttribute(attr);
	if (v != undefined && re.test(v)) {
		return RegExp.$1;
	} else {
		return deflt;
	}
  },

  render: function (id){
	var obj = document.getElementById(id);
	var white = CHESS.get(obj, "white", /(.+)/, "Ra1Nb1Bc1Qd1Ke1Bf1Ng1Rh1pa2pb2pc2pd2pe2pf2pg2ph2");
	var black = CHESS.get(obj, "black", /(.+)/, "Ra8Nb8Bc8Qd8Ke8Bf8Ng8Rh8pa7pb7pc7pd7pe7pf7pg7ph7");
	var size = CHESS.get(obj, "size", /(\d+)/, 30);
	var whitebox = CHESS.get(obj, "whitebox", /([\da-fA-F]+)/, "f0f0e9");
	var blackbox = CHESS.get(obj, "blackbox", /([\da-fA-F]+)/, "669988");
	var b = '<table width="'+size*10+'" cellspacing="0" bgcolor="#'+whitebox+'">';
	b += CHESS.file_marks(size);
	for (var rank = 8; rank > 0; rank--) {
		var rowcolors = [' bgcolor="#'+blackbox+'"', ""];
		if (rank%2 == 0) rowcolors = ["", rowcolors[0]];
		b += '<tr height="'+size+'"><td bgcolor="white" align="right">'+rank+'</td>';
		for (var file = 8; file > 0; file--) {
			var pos = CHESS.Files[8-file]+rank;
			var piece = CHESS.get_piece(pos, white);
			if (piece.length > 0) {
				//piece = '<div align="center" style="font-weight:bold; color:white">'+ piece +'</div>';
				piece = '<img src="/im/'+piece.toLowerCase()+'l.png"/>';
			} else {
				piece = CHESS.get_piece(pos, black);
				if (piece.length > 0) {
					//piece = '<div align="center" style="font-weight:bold; color:black">'+ piece +'</div>';
					piece = '<img src="/im/'+piece.toLowerCase()+'d.png"/>';
				}
			}
        		b += '<td'+rowcolors[file%2]+'>'+piece+'</td>';
    		}
    		b += '<td bgcolor="white">'+rank+"</td></tr>\n";
	}
	b += CHESS.file_marks(size) + "</table>\n";
	DYN.ih(id, b);
	return;
  },

  file_marks: function (size) {
	var row = '<tr bgcolor="white"><td width="5"/>';
	for (var c = 1; c <= 8; c++) {
		row += '<td align="center" width="'+size+'">'+ CHESS.Files[c-1] +'</td>';
	}
	row += '<td/></tr>';
	return row;
  },

  get_piece: function (pos, str) {
	var re = new RegExp('([KQRNBp])'+pos, 'i');
	return re.test(str) ? RegExp.$1 : "";
  }
};

COUNTDOWN = {
  Autotag: '<div id="ctdown" type=countdown till="2009/1/19 23:59:59" heading="Time left for the Bush Dynasty" message="Good riddance!" style="font-size:20pt;color:#6699cc"></div>',
  obj: "",
  endtime: 0,
  interval: 1000,
  pause: false,
  dt: function() {
	var now = new Date();
	return COUNTDOWN.endtime - now.getTime();
  },

  render: function(id) {
	var obj = document.getElementById(id);
	var till = obj.getAttribute('till');
	COUNTDOWN.interval = DYN.get_attr(obj, 'interval', /(\d+)/, 1000);
	if (/(\d+)\D(\d+)\D(\d+)\D(\d+)\D(\d+)\D(\d+)/.test(till)) {
		var y = RegExp.$1;
		if (y.length < 4) y += 2000;
		COUNTDOWN.endtime = new Date(y, RegExp.$2 -1, RegExp.$3, RegExp.$4, RegExp.$5, RegExp.$6);
		COUNTDOWN.div_id = RANDOM.id('CD');
		var descr = obj.getAttribute('heading');
		if (descr == undefined) descr = 'Count down to '+COUNTDOWN.endtime;
		obj.innerHTML = descr+'<div id="'+COUNTDOWN.div_id+'" onclick="return COUNTDOWN.toggle_pause();"></div>';
		COUNTDOWN.obj = obj;
		COUNTDOWN.loop();
	} else {
		obj.innerHTML = 'Error: invalid endtime.';
	}
  },
  loop: function () {
	if (COUNTDOWN.pause) return;
	var t = COUNTDOWN.dt();
	var s = (t <= 0) ? COUNTDOWN.obj.getAttribute('message') : COUNTDOWN.time(t);
	DYN.ih(COUNTDOWN.div_id, s);
	setTimeout("COUNTDOWN.loop()", COUNTDOWN.interval);
  },
  time: function (t) {
	var s = "";
	if (COUNTDOWN.interval < 1000) {
		s = t%1000+'msec';
	}
	t = Math.floor(t/1000);
	var n = [60, 60, 24];
	var u = ['"', "'", 'h'];
	for(var i = 0; i < n.length; i++) {
		s = t%n[i]+u[i]+' '+s;
		if (t < n[i]) return s;
		t = Math.floor(t/n[i]);
	}
	if (t > 0) {
		s = t + (t > 1?' days ' : ' day ') + s;
	}
	return s;
  },
  toggle_pause: function() {
	if (COUNTDOWN.pause) {
		COUNTDOWN.pause = false;
		COUNTDOWN.loop();
		return false;
	}
	COUNTDOWN.pause = true;
  }
};

CENSOR = {
  Autotag: '<span type="censor"></span>',
  RE: /(\S*f\W?u\W?c\W?k\S*|s\W?h\W?i\W?t|c\W?o\W?c\W?k\W?s\W?u\W?c\W?k\W?e\W?r|c\W?u\W?n\W?t)/ig,
  Orig: new Array(),
  abash: function(s) {
	var len = s.length;
	var ab = "";
	for(var i=0; i<len; i++){
		var c = s.charCodeAt(i);
		// 65-90 A-Z, 97-122 a-z
		if (c == 32) {
			ab += ' ';
			continue;
		}
		if ((c >= 48 && c <= 57) || (c > 90 && c < 97)) {
			ab += s.charAt(i);
			continue;
		}
		if (c < 65 || c > 122) {
			ab += '*';
			continue;
		}
		if (c <= 90) {
			c += 32; // abash in lower case only
		}
		ab += String.fromCharCode(219-c);
	}
	return ab
  },
  ignore: function(obj, id) {
	var txt = obj.innerHTML;
	if (obj.innerHTML == CENSOR.Orig[id]) return false;
	if (confirm("Censored text may be a spoiler or offensive to some people.  Do you really want to continue?"))
		obj.innerHTML = CENSOR.Orig[id];
	return false;
  },
  render: function(obj) {
	var spans = obj.getElementsByTagName("span");
	for(var i = 0; i < spans.length; i++) {
		var sp = spans[i];
		if (sp.getAttribute("type") != "censor") {
			continue;
		}
		var cnsr_id = RANDOM.id("_cnsr");
		sp.id = cnsr_id;
		var orig = sp.innerHTML;
		CENSOR.Orig[cnsr_id] = orig;
		sp.innerHTML = '<a style="color:#999999" title="Censored text may be a spoiler or offensive to some people." onclick="CENSOR.ignore(this,\''+cnsr_id+'\');">'+CENSOR.abash(orig)+'</a>';
	}
	var tags = obj.getElementsByTagName("censor");
	for(var i = 0; i < tags.length; i++) {
		var censor = tags[i];
		censor.id = RANDOM.id("_cnsr");
		var orig = censor.innerHTML;
		CENSOR.Orig[censor.id] = orig;
		try {
			censor.innerHTML = '<a style="color:#999999" title="Censored text may be a spoiler or offensive to some people." onclick="CENSOR.ignore(this,\''+censor.id+'\');">'+CENSOR.abash(orig)+'</a>';
		} catch(e) { return }
	}
  }
};

SECRET = {
  Autotag: '<div type="aesctr" key="">Make sure nobody is watching and enter your secret here.\nMemorize your key or you will need NSA to get your secret back.</div>',
  render: function(obj) {
	obj.id = RANDOM.id("_aes");
	obj.innerHTML = '<pre style="font-size:8pt;color:#9966cc">'+obj.innerHTML.replace(/(\S{100})/g, "$1\n")+'</pre>Key: <input id="'+obj.id+'key" style="font-size:6pt" type="password" onKeyPress="SECRET.checkkey(event,\''+obj.id+'\')" /> <input type=button style="font-size:6pt" value="?" onclick="SECRET.reveal(\''+ obj.id +'\'); return false;" />';
	
  },
  render_all: function(obj) {
	var tags = obj.getElementsByTagName("aesctr");
	for(var i = 0; i<tags.length; i++) {
		SECRET.render(tags[i]);
	}
  },
  checkkey: function(e, id){
	var code;
	if(e && e.which){
		code = e.which;
	}else{
		code = event.keyCode;
	}
	if(code == 13){
		SECRET.reveal(id);
	}
	return false;
  },
  unesc: function(str){
        return str.replace(/%26/ig, '&').replace(/%3b/ig, ';').replace(/%0a/ig, "\n").replace(/%2b/ig, '+');
  },
  reveal: function(id){
	var secret = document.getElementById(id);
	if(!secret)return false;
	var key = document.getElementById(id+'key').value;
	if (!key || key.length == 0) {
		alert("Please enter key.");
		return false;
	}
	var crypt = secret.innerHTML.replace(/^<pre .*?>/i, "").replace(/<\/pre>.*/i, "");
	var plain = CTR_AES_decrypt(decode64(crypt), key);
	if (plain && plain.length > 0) {
		plain = SECRET.unesc(plain);
		secret.innerHTML = '<textarea cols="180" rows="10" readonly disabled>'+plain+'</textarea>';
	}
	return false;
  }
};

function CODE_render(id) {
	var obj = document.getElementById(id);
	obj.style.border = "1px solid #66cc99";
	DYN.ih(id, '<pre>'+obj.innerHTML.replace(/</g, '&lt;')+'</pre>');
}

function RULES_show (xml) {
	var post = document.getElementById('forum_rules');
	var rules = DYN.xml_value(xml, 'rules');
	rules = rules.replace(/#(\/?[a-z]+)/g, "<$1>");
	post.innerHTML = '<table align="center" width="500" style="font-weight:bold"><tr><td>'+rules+'</td></tr><tr height="20" /></table>';
	POSTIT.render([post]);
}
